# -*- coding: utf-8 -*-
"""
智慧职教MOOC视频下载器 - 下载统计模块
记录和展示下载统计信息，生成详细报告
"""

import time
from datetime import datetime, timedelta
from typing import Dict, List, Any, Optional
from dataclasses import dataclass, field
from pathlib import Path
import json
from logger import logger


@dataclass
class CourseStats:
    """单个课程的统计信息"""
    course_name: str
    total_videos: int = 0
    downloaded_videos: int = 0
    failed_videos: int = 0
    skipped_videos: int = 0
    start_time: Optional[datetime] = None
    end_time: Optional[datetime] = None
    errors: List[str] = field(default_factory=list)
    
    @property
    def success_rate(self) -> float:
        """成功率"""
        if self.total_videos == 0:
            return 0.0
        return self.downloaded_videos / self.total_videos
    
    @property
    def duration(self) -> Optional[timedelta]:
        """处理耗时"""
        if self.start_time and self.end_time:
            return self.end_time - self.start_time
        return None
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            'course_name': self.course_name,
            'total_videos': self.total_videos,
            'downloaded_videos': self.downloaded_videos,
            'failed_videos': self.failed_videos,
            'skipped_videos': self.skipped_videos,
            'success_rate': self.success_rate,
            'start_time': self.start_time.isoformat() if self.start_time else None,
            'end_time': self.end_time.isoformat() if self.end_time else None,
            'duration_seconds': self.duration.total_seconds() if self.duration else None,
            'errors': self.errors
        }


class StatisticsManager:
    """统计管理器"""
    
    def __init__(self):
        self.start_time = datetime.now()
        self.end_time: Optional[datetime] = None
        self.total_pages = 0
        self.processed_pages = 0
        self.total_courses = 0
        self.successful_courses = 0
        self.failed_courses = 0
        self.course_stats: Dict[str, CourseStats] = {}
        self.global_errors: List[str] = []
        
    def start_course_processing(self, course_name: str) -> CourseStats:
        """开始处理课程"""
        stats = CourseStats(
            course_name=course_name,
            start_time=datetime.now()
        )
        self.course_stats[course_name] = stats
        logger.debug(f"开始统计课程: {course_name}")
        return stats
    
    def finish_course_processing(self, course_name: str, success: bool = True):
        """完成课程处理"""
        if course_name in self.course_stats:
            stats = self.course_stats[course_name]
            stats.end_time = datetime.now()
            
            if success:
                self.successful_courses += 1
            else:
                self.failed_courses += 1
                
            logger.debug(f"完成统计课程: {course_name}, 成功: {success}")
    
    def update_course_stats(self, course_name: str, **kwargs):
        """更新课程统计信息"""
        if course_name in self.course_stats:
            stats = self.course_stats[course_name]
            for key, value in kwargs.items():
                if hasattr(stats, key):
                    setattr(stats, key, value)
    
    def add_course_error(self, course_name: str, error: str):
        """添加课程错误"""
        if course_name in self.course_stats:
            self.course_stats[course_name].errors.append(error)
        logger.debug(f"记录课程错误: {course_name} - {error}")
    
    def add_global_error(self, error: str):
        """添加全局错误"""
        self.global_errors.append(error)
        logger.debug(f"记录全局错误: {error}")
    
    def finish_session(self):
        """结束会话"""
        self.end_time = datetime.now()
        self.total_courses = len(self.course_stats)
    
    def get_summary(self) -> Dict[str, Any]:
        """获取统计摘要"""
        duration = None
        if self.end_time:
            duration = self.end_time - self.start_time
        
        total_videos = sum(stats.total_videos for stats in self.course_stats.values())
        downloaded_videos = sum(stats.downloaded_videos for stats in self.course_stats.values())
        failed_videos = sum(stats.failed_videos for stats in self.course_stats.values())
        skipped_videos = sum(stats.skipped_videos for stats in self.course_stats.values())
        
        overall_success_rate = downloaded_videos / total_videos if total_videos > 0 else 0
        
        return {
            'session_info': {
                'start_time': self.start_time.isoformat(),
                'end_time': self.end_time.isoformat() if self.end_time else None,
                'duration_seconds': duration.total_seconds() if duration else None,
                'duration_formatted': str(duration).split('.')[0] if duration else None
            },
            'page_stats': {
                'total_pages': self.total_pages,
                'processed_pages': self.processed_pages
            },
            'course_stats': {
                'total_courses': self.total_courses,
                'successful_courses': self.successful_courses,
                'failed_courses': self.failed_courses,
                'success_rate': self.successful_courses / self.total_courses if self.total_courses > 0 else 0
            },
            'video_stats': {
                'total_videos': total_videos,
                'downloaded_videos': downloaded_videos,
                'failed_videos': failed_videos,
                'skipped_videos': skipped_videos,
                'overall_success_rate': overall_success_rate
            },
            'error_stats': {
                'global_errors_count': len(self.global_errors),
                'courses_with_errors': len([s for s in self.course_stats.values() if s.errors])
            }
        }
    
    def print_summary(self):
        """打印统计摘要"""
        summary = self.get_summary()
        
        logger.info("=" * 80)
        logger.info("📊 下载统计报告")
        logger.info("=" * 80)
        
        # 会话信息
        session = summary['session_info']
        logger.info(f"⏰ 会话时间: {session['start_time'][:19]} - {session['end_time'][:19] if session['end_time'] else '进行中'}")
        if session['duration_formatted']:
            logger.info(f"⏱️  总耗时: {session['duration_formatted']}")
        
        # 页面统计
        page = summary['page_stats']
        logger.info(f"📄 页面处理: {page['processed_pages']}/{page['total_pages']} 页")
        
        # 课程统计
        course = summary['course_stats']
        logger.info(f"📚 课程处理: {course['successful_courses']}/{course['total_courses']} 门课程 (成功率: {course['success_rate']:.1%})")
        
        # 视频统计
        video = summary['video_stats']
        logger.info(f"🎥 视频下载: {video['downloaded_videos']}/{video['total_videos']} 个视频 (成功率: {video['overall_success_rate']:.1%})")
        if video['skipped_videos'] > 0:
            logger.info(f"⏭️  跳过视频: {video['skipped_videos']} 个")
        if video['failed_videos'] > 0:
            logger.info(f"❌ 失败视频: {video['failed_videos']} 个")
        
        # 错误统计
        errors = summary['error_stats']
        if errors['global_errors_count'] > 0 or errors['courses_with_errors'] > 0:
            logger.info(f"⚠️  错误统计: 全局错误 {errors['global_errors_count']} 个, 课程错误 {errors['courses_with_errors']} 门")
        
        logger.info("=" * 80)
    
    def print_detailed_report(self):
        """打印详细报告"""
        self.print_summary()
        
        # 课程详细信息
        if self.course_stats:
            logger.info("\n📋 课程详细信息:")
            logger.info("-" * 60)
            
            for i, (course_name, stats) in enumerate(self.course_stats.items(), 1):
                status = "✅" if stats.success_rate >= 0.9 else "⚠️" if stats.success_rate >= 0.5 else "❌"
                duration_str = f" ({str(stats.duration).split('.')[0]})" if stats.duration else ""
                
                logger.info(f"{i:2d}. {status} {course_name}")
                logger.info(f"     视频: {stats.downloaded_videos}/{stats.total_videos} "
                          f"(成功率: {stats.success_rate:.1%}){duration_str}")
                
                if stats.errors:
                    logger.info(f"     错误: {len(stats.errors)} 个")
                    for error in stats.errors[:3]:  # 只显示前3个错误
                        logger.info(f"       - {error}")
                    if len(stats.errors) > 3:
                        logger.info(f"       ... 还有 {len(stats.errors) - 3} 个错误")
        
        # 全局错误
        if self.global_errors:
            logger.info(f"\n⚠️ 全局错误 ({len(self.global_errors)} 个):")
            logger.info("-" * 60)
            for i, error in enumerate(self.global_errors[:10], 1):  # 只显示前10个
                logger.info(f"{i:2d}. {error}")
            if len(self.global_errors) > 10:
                logger.info(f"... 还有 {len(self.global_errors) - 10} 个错误")
    
    def save_report(self, filename: Optional[str] = None):
        """保存报告到文件"""
        if not filename:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"mooc_download_report_{timestamp}.json"
        
        report_data = {
            'summary': self.get_summary(),
            'course_details': {name: stats.to_dict() for name, stats in self.course_stats.items()},
            'global_errors': self.global_errors,
            'generated_at': datetime.now().isoformat()
        }
        
        try:
            reports_dir = Path("reports")
            reports_dir.mkdir(exist_ok=True)
            
            report_file = reports_dir / filename
            with open(report_file, 'w', encoding='utf-8') as f:
                json.dump(report_data, f, ensure_ascii=False, indent=2)
            
            logger.info(f"📄 详细报告已保存到: {report_file}")
            return str(report_file)
            
        except Exception as e:
            logger.error(f"保存报告失败: {e}")
            return None
    
    def get_top_failed_courses(self, limit: int = 5) -> List[CourseStats]:
        """获取失败率最高的课程"""
        failed_courses = [
            stats for stats in self.course_stats.values() 
            if stats.success_rate < 1.0
        ]
        return sorted(failed_courses, key=lambda x: x.success_rate)[:limit]
    
    def get_fastest_courses(self, limit: int = 5) -> List[CourseStats]:
        """获取处理最快的课程"""
        completed_courses = [
            stats for stats in self.course_stats.values() 
            if stats.duration is not None
        ]
        return sorted(completed_courses, key=lambda x: x.duration)[:limit]


# 全局统计实例
stats_manager = StatisticsManager() 